package com.kili.cloud.shorturl.service;

import com.kili.cloud.common.exception.ExceptionUtils;
import com.kili.cloud.common.util.RedisLock;
import com.kili.cloud.shorturl.vo.ShortUrlContext;
import com.kili.cloud.shorturl.vo.ShortUrlParam;
import com.kili.common.Exception.ExceptionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @description 长链接处理对象抽象类
 * @author tom.liu
 * @date 2019/6/16 23:16
 */
public abstract  class AbstractShortUrl {
    private static Logger logger = LoggerFactory.getLogger(AbstractShortUrl.class);

    private static final String LOCK_CLIEN_NAME = "SHORT_URL";

    private static final String LOCK_PRE = "SHORT_URL:";
    /**
     * 服务上下文
     */
    ShortUrlContext context = new ShortUrlContext();


    @Autowired
    RedisLock redisLock;


    /**
     * 功能描述: 长链接转短链接的模板方法
     * @param param 长链接信息
     * @return String 短链接
     * @author tom.liu
     * @date 2019/6/16 23:24
     */
    public String input(ShortUrlParam param){
        logger.debug("长链接转短链接服务业务处理开始");
        validateInput(param);
        String url;

        //加锁存入
        String lockKey = LOCK_PRE + context.getHashCode() + "_" + context.getCustomerId();
        boolean getLockFlag = redisLock.distributedLock(lockKey, LOCK_CLIEN_NAME, 60);
        if(getLockFlag) {
            try {
                url = inputBussiness(param);
            } finally {
                redisLock.releaseDistributedLock(lockKey, LOCK_CLIEN_NAME);
            }
        }else{
            logger.info("该客户相同url存入正在处理");
            throw  ExceptionUtils.getBussinessException(ExceptionType.BIZ_VERIFY_ERROR, "500", "the url was locked, please wait" );
        }

        logger.debug("长链接转短链接服务业务处理结束");
        return url;
    }

    /**
     * 功能描述: 短链接得到原链接的模板方法
     * @param uri 压缩后的短链接
     * @param ip 调用方的ip地址
     * @return String 原链接
     * @author tom.liu
     * @date 2019/6/16 23:25
     */
    public String visit(String uri, String ip){
        validateVisit(uri, ip);
        String originalUrl = visitBussiness(uri);
        return originalUrl;
    }

    /**
     * 功能描述: 校验长链接输入信息
     * @param param 长链接信息
     * @return
     * @author tom.liu
     * @date 2019/6/16 23:26
     */
    public abstract void validateInput(ShortUrlParam param);

    /**
     * 功能描述: 校验输入短链接信息
     * @param uri 短链接
     * @param ip 调用方的ip地址
     * @return
     * @authortom.liu
     * @date  2019/6/16 23:26
     */
    public abstract void validateVisit(String uri, String ip);

    /**
     * 功能描述: 长链接转短链接的业务处理方法
     * @param param 长链接信息
     * @return String 压缩后的短链接
     * @author tom.liu
     * @date 2019/6/16 23:26
     */
    public abstract String inputBussiness(ShortUrlParam param);

    /**
     * 功能描述: 短链接转原链接的业务处理方法
     * @param uri 压缩后的短链接
     * @return String 原链接
     * @author tom.liu
     * @date 2019/6/16 23:27
     */
    public abstract String visitBussiness(String uri);


    public ShortUrlContext getContext() {
        return context;
    }

    public void setContext(ShortUrlContext context) {
        this.context = context;
    }
}
